﻿using Furion.CMS.Core;
using Furion.CMS.Core.EventSource;
using Furion.CMS.Core.Handlers;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.EventBus;
using Furion.TaskScheduler;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Domain
{
    public class UserPermissionFormatHandler : AuditLogFormatHandler
    {
        public override string GetRowKey(DbContext context, object entityValues, params string[] formatArgs)
        {
            if (entityValues is PropertyValues values)
            {
                var uid = values.GetValue<int>(nameof(UserPermission.UserId));

                var user = context.Find<UserInfo>(uid);
                if (user == null) return "未知";

                return user.NickName;
            }
            return "未知";
        }

        public override string[] GetChangeValue(DbContext context, object oldValue, object newValue)
        {
            var oldUser = context.Find<PermissionInfo>(oldValue);
            var newUser = context.Find<PermissionInfo>(newValue);

            return new string[2] { oldUser?.Name ?? "无", newUser?.Name ?? "无" };
        }
    }

    /// <summary>
    /// 用户权限
    /// <para>
    /// 独立于角色之外,用于权限范围控制的补充
    /// </para>
    /// </summary>
    [OperateRecord("用户权限")]
    public class UserPermission : IEntity,
        IEntityTypeBuilder<UserPermission>,
        IEntityChangedListener<UserPermission>
    {
        /// <summary>
        /// 用户id
        /// </summary>
        [OperateRecord("用户id", true, typeof(UserPermissionFormatHandler))]
        public int UserId { get; set; }

        /// <summary>
        /// 用户信息
        /// </summary>
        public virtual UserInfo User { get; set; }

        /// <summary>
        /// 权限代码
        /// </summary>
        [MaxLength(200), Required]
        [OperateRecord("权限代码")]
        public string PermissionCode { get; set; }
        /// <summary>
        /// 权限信息
        /// </summary>
        public virtual PermissionInfo Permission { get; set; }

        public void Configure(EntityTypeBuilder<UserPermission> entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            entityBuilder.UseDefaultTableNameDefine();

            entityBuilder.HasIndex(i => new { i.UserId, i.PermissionCode });
        }

        public void OnChanged(UserPermission newEntity, UserPermission oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)
        {
            SpareTime.DoIt(() =>
            {
                Scoped.Create((_, scope) =>
                {
                    var services = scope.ServiceProvider;
                    // 获取数据库上下文
                    var dbContext = Db.GetDbContext(services);

                    var operationType = CacheOperationType.Add;
                    if (state == EntityState.Detached)
                    {// 移除
                        operationType = CacheOperationType.Remove;
                    }
                    // 触发事件
                    var eventPublisher = services.GetService<IEventPublisher>();
                    // 补充权限信息
                    newEntity.Permission = newEntity.Permission ?? dbContext.Set<PermissionInfo>().Find(newEntity.PermissionCode);
                    newEntity.User = newEntity.User ?? dbContext.Set<UserInfo>().Find(newEntity.UserId);
                    dbContext.Attach(newEntity.User).Collection(c => c.Passports).Load();
                    // 获取当前角色变更模块的权限依赖
                    if (!string.IsNullOrWhiteSpace(newEntity.Permission.DependentResources))
                    {
                        var dependentResList = newEntity.Permission.DependentResources.Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        var resourcePayload = new string[] { string.Format(CacheKeyConsts.PermissionResourceValue, Guid.Empty, newEntity.UserId) };
                        var changeEvents = dependentResList.Select(s => new OnPermissionDataItemChange(operationType, string.Format(CacheKeyConsts.PermissionResource, s, ""), resourcePayload));
                        // 更新资源缓存
                        eventPublisher?.PublishAsync(new ChannelEventSource(EventIdConsts.PermissionDataItemManyChange, changeEvents));
                    }
                    // 更新账号模块
                    var account = newEntity.User.Passports.FirstOrDefault(x => x.Type == PassportType.Normal)?.Account;
                    eventPublisher?.PublishAsync(new OnPermissionDataItemChange(operationType, string.Format(CacheKeyConsts.PermissionModule, account, ""), new string[] { newEntity.Permission.Code }));

                });
            });


        }
    }
}
